﻿using System;
using Pay.IService;
using Pay.DTO;
using Pay.Core;
using System.Collections.Generic;
using System.Linq;
using Pay.Data;
using Pay.TO;

namespace Pay.Service {
    public class TokenMallBillService : MallBillService, IMallBillService {
        private IOrderService _iOrderService;
        private IPayHtmlService _iPayhtmlService;
        private IMessagePushService _iMessagePushService;
        private IProductService _iProductService;
        private IUnitOfWork _iUnitOfWork;
        private ISoupTaskService _iSoupTaskService;
        private ITokenUserService _iTokenUserService;
        private ITokenBillService _iTokenBillService;
        private static readonly object dbwaitLock = new object();

        public TokenMallBillService(IUnitOfWork iUnitOfWork, IOrderService iOrderService, IProductService iProductService,
                                    IPayHtmlService iPayhtmlService, IMessagePushService iMessagePushService,
                                    IMerchantService iMerchantService, ISettingService isettingservice,
                                    ISoupTaskService iSoupTaskService, ITokenUserService iTokenUserService,
                                    ITokenBillService iTokenBillService) : base(iUnitOfWork, iMerchantService, isettingservice, iProductService) {
            _iOrderService = iOrderService;
            _iPayhtmlService = iPayhtmlService;
            _iMessagePushService = iMessagePushService;
            _iProductService = iProductService;
            _iUnitOfWork = iUnitOfWork;
            _iSoupTaskService = iSoupTaskService;
            _iTokenBillService = iTokenBillService;
            _iTokenUserService = iTokenUserService;
        }
        public void PaySuccess(string payNo, string transaction_no, DateTime? pay_time) {
            bool isFinish = false;
            var cacheList = new List<string>();
            lock (dbwaitLock) {
                var orders = context.Orders.Where(c => c.PayInfo.PayNo == payNo).ToList();
                foreach (var order in orders) {
                    if (order.Status != OrderStatus.WaitPay)
                        return;
                    order.Status = OrderStatus.WaitDelivery;
                    order.PayInfo.TransactionNo = transaction_no;
                    order.PayInfo.PayTime = (pay_time.HasValue ? pay_time.Value.ToUnix() : DateTime.Now.ToUnix());
                    _iProductService.MinusStock(order, cacheList);
                    //卖家货款
                    AddSellerAccount(order);
                    //生成临时推单数据
                    if (order.OrderType == 1 || order.OrderType == 2) {
                        var pay_html = new PayHtml {
                            Id = DtoHelper.GenerateOrderNumber(),
                            Charge = order.ToJson(),
                            Html = order.ToJson(),
                            CreateTime = order.OrderTime,
                            MerchantNo = order.Merchant.MerchantNo,
                            OrderNo = order.OrderNo,
                            PayType = (order.OrderType == 1 ? RequestMethod.TOKEN_HTML_ORDER : RequestMethod.TOKEN_HNIAO_ORDER),
                            IsFinish = 0
                        };
                        context.PayHtmls.Add(pay_html);
                    }
                    var binds = order.Binds.ToObject<List<bind_merchant_item>>();
                    //分润账单
                    foreach (var item in order.OrderItems) {
                        var sku_id = item.SkuId ?? 0;
                        var profits = binds.Where(c => c.product_id == item.ProductId && c.sku_id == sku_id).ToList();
                        var busType = (item.ActiveType == 1 ? TO.BusType.UpGrade : TO.BusType.Mall);
                        TokenMallProfitAccount(order, profits, busType);
                        if (ProfiTables.Count > 0)
                            context.Profits.AddRange(ProfiTables);
                        if (item.ActiveType == 1 && !isFinish) {
                            //将用户升级成创客
                            _iTokenUserService.TokenUpgradeMaker(order.BuyId.Value);
                            cacheList.Add("Merchant" + order.BuyId.Value);
                            isFinish = true;
                        }
                    }
                    ProfiTables.Clear();
                    //红砖兑换活动业务
                    if (order.RedDrill > 0)
                        RedDrillLogic(order, cacheList);
                    //平台账单
                    var plat_amount = order.PayAmount - order.Amount - order.DisAmount;
                    plat_amount = plat_amount + order.DisAmount - binds.Sum(c => c.amount);
                    if (plat_amount > 0)
                        AddMallMerchantAccount(order, plat_amount, 1);
                    if (order.OrderType != 7) {
                        #region 向购买人发送消息          
                        var msgList = _iSettingService.GetTokenSetting().msg;
                        if (order.BuyId.HasValue && order.BuyId.Value > 0) {//登陆后购买，发送极光消息
                            string product_name = (order.OrderItems.Count > 1 ? order.OrderItems.FirstOrDefault().ProductName + "更多" : order.OrderItems.FirstOrDefault().ProductName);
                            if (order.OrderItems.FirstOrDefault().ProductId != 0) {
                                var user_buy_product = msgList.Where(o => o.code == "tokenmall_buy_product").FirstOrDefault();
                                var buyerMessage = new MessagePush();
                                buyerMessage.MerchantId = order.BuyId.Value;
                                buyerMessage.Type = MsgType.OrderBuy;
                                buyerMessage.Title = user_buy_product.name;
                                buyerMessage.ShortContent = string.Format(user_buy_product.content, product_name);
                                buyerMessage.Content = string.Format(user_buy_product.content, product_name);
                                buyerMessage.Ext = "{}";
                                buyerMessage.CreateTime = DateTime.Now.ToUnix();
                                buyerMessage.ObjectId = order.Id;
                                context.MessagePushs.Add(buyerMessage);
                                messages.Add(buyerMessage.ToDtoObject<message_push_dto>());
                            }
                        } else {//匿名购买发送手机短信
                            try {
                                string product_name = order.OrderItems.FirstOrDefault().ProductName;
                                product_name = (product_name.Length > 7 ? product_name.Substring(0, 7) + "..." : product_name);
                                string orderLogisticsUrl = t_RequestMethod.token_url + "MyOrder/OrderLogistics?order_id=" + order.Id;//查询物流信息的URL地址
                                string shortUrl = ShortLinkHelper.GetShortLink(orderLogisticsUrl);
                                string msgContent = string.Format("您在拓垦应用内购买的【{0}】已经支付成功等待商家发货，物流跟进地址：{1}", product_name, shortUrl);
                                _iSettingService.SendTokenSms(order.Shipping.Phone, msgContent);
                            } catch {

                            }

                        }
                        #endregion

                        #region 向卖家发送消息
                        var user_sell_product = msgList.Where(o => o.code == "tokenmall_sell_product").FirstOrDefault();
                        var sellerMessage = new MessagePush();
                        sellerMessage.MerchantId = order.MerchantId;
                        sellerMessage.Type = MsgType.OrderBuyToSeller;
                        sellerMessage.Title = user_sell_product.name;
                        sellerMessage.ShortContent = user_sell_product.content;
                        sellerMessage.Content = user_sell_product.content;
                        sellerMessage.Ext = "{}";
                        sellerMessage.CreateTime = DateTime.Now.ToUnix();
                        sellerMessage.ObjectId = order.Id;
                        sellerMessage.Url = t_RequestMethod.token_url + "myorder/sellerorderdetail?order_id=" + order.Id;
                        context.MessagePushs.Add(sellerMessage);
                        messages.Add(sellerMessage.ToDtoObject<message_push_dto>());
                    }
                   
                    #endregion
                }
                int result = _iUnitOfWork.Commit(cacheList.ToArray());
                if (result > 0) PushMessage(messages);

                #region 购买商品加马力
                foreach (var order in orders) {
                    if (order.BuyId.HasValue && order.BuyId.Value > 0) {
                        var orderDto = order.ToDtoObject<order_dto>();
                        try {
                            var taskResult = _iSoupTaskService.TaskRecive(order.BuyId.Value, TO.ETaskType.MallShopping, orderDto.id).Result;
                        } catch {
                        }
                    }
                }
                #endregion
            }
        }
        /// <summary>
        /// 处理红砖业务
        /// </summary>
        /// <param name="order"></param>
        private void RedDrillLogic(Order order, List<string> cacheList) {
            var createTime = DateTime.Now.ToUnix();
            long redDrillReceiverId = order.MerchantId;//卖家
            if (order.RedDrillReceiverId.HasValue && order.RedDrillReceiverId.Value > 0)
                redDrillReceiverId = order.RedDrillReceiverId.Value;
            //todo：扣买家红砖、卖家增加红砖且红砖状态为【冻结】。
            var buyRedRecord = context.RedRecord.FirstOrDefault(s => s.MerchantId == order.BuyId);
            var sellRedRecord = context.RedRecord.FirstOrDefault(s => s.MerchantId == redDrillReceiverId);
            if (sellRedRecord == null) {
                sellRedRecord = new RedRecord {
                    MerchantId = redDrillReceiverId,
                    FrozenRedDrill = order.RedDrill,
                    CreateTime = createTime,
                    RegisterTime = createTime,
                    NextProductionTime = createTime,
                    InvitationCode = InvitationCodeHelp.toSerialCode(redDrillReceiverId),
                    DayRedDrill = "{}",
                    TotalHorsePower = 0,
                    IsFinish = false,
                    TotalRedDrill = 0,
                    InvitationCodeNum = 0,
                    ConsumeRedDrill = 0
                };
                context.RedRecord.Add(sellRedRecord);
            } else {
                sellRedRecord.FrozenRedDrill += order.RedDrill;//卖家增加冻结红钻
            }
            //买家消费明细
            RedRecordDetail buy_detail = new RedRecordDetail();
            buy_detail.MerchantId = buyRedRecord.MerchantId;
            buy_detail.HorsePower = 0;
            buy_detail.RedDrill = order.RedDrill;
            buy_detail.Type = 5;
            buy_detail.IsReceive = true;
            buy_detail.ReceiveTime = DateTime.Now.ToUnix();
            buy_detail.CreateTime = DateTime.Now.ToUnix();
            buy_detail.RedProductionTime = 0;
            buy_detail.RedRecordId = buyRedRecord.Id;
            //冻结卖家获得红钻
            RedFrozenRecord fRecord = new RedFrozenRecord();
            fRecord.MerchantId = redDrillReceiverId;
            fRecord.OrderId = order.Id;
            fRecord.RedDrill = order.RedDrill;
            fRecord.RecordType = 1;
            fRecord.Type = 0;
            fRecord.CreateTime = DateTime.Now.ToUnix();
            context.RedRecordDetail.Add(buy_detail);
            context.RedFrozenRecord.Add(fRecord);
            buyRedRecord.ConsumeRedDrill += order.RedDrill; //买家增加消费红钻
            cacheList.Add("RedRecord" + order.BuyId.Value);
            cacheList.Add("RedRecord" + redDrillReceiverId);
        }

        private void PushMessage(List<message_push_dto> messages) {
            JPushHelp jPushHelp = new JPushHelp(t_RequestMethod.push_app_key, t_RequestMethod.push_app_secret);
            foreach (var message in messages) {
                var merchant = context.Merchants.FirstOrDefault(c => c.Id == message.user_id);
                if (!string.IsNullOrEmpty(message.url))
                    jPushHelp.Push(message.title, message.content, (int)message.type, message.object_id.Value, new List<string> { merchant.Mobile }, message.url);
                else
                    jPushHelp.Push(message.title, message.content, (int)message.type, message.object_id.Value, new List<string> { merchant.Mobile });
            }
        }
    }
}
